import React, { Component } from 'react';
import { Icon, Popover, Tooltip, Input, Button, message } from 'antd';
import PropTypes from 'prop-types';
import Tag, { tagColors } from '@components/tag';
import { clone, get, intersection } from 'lodash';
import { addTag, deleteTag, updateTag } from '@api/tag';
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import { actions as tagActions } from '@redux/reducer/tag';
import ColorBlocks from '@components/color-blocks';
import './index.less';

const defaultSelectColor = '#8acaf9';

class TagSelect extends Component {
  static defaultState = {
    mode: 'select', // select: 选择页 、edit: 编辑页、new: 新增页
    searchInputValue: '',
    selectColor: defaultSelectColor
  };
  constructor(props) {
    super(props);
    this.state = {
      ...TagSelect.defaultState,
      popoverVisible: false,

      currentTag: {},

      selected: props.selected || [],
      onAddingTag: false,
      onUpdatingTag: false,
      onDeleteingTag: false
    };
  }

  // eslint-disable-next-line
  UNSAFE_componentWillReceiveProps(props) {
    if (this.props.selected !== props.selected) {
      this.setState({
        selected: props.selected
      });
    }
  }

  loadTagsList = () => {
    this.props.loadTags();
  };

  wrapChangeMode = (mode, currentTag = {}) => e => {
    e.stopPropagation();
    const { name: searchInputValue = '', color: selectColor = defaultSelectColor } = currentTag;
    this.setState({ mode, currentTag, searchInputValue, selectColor });
  };

  wrapChangePopover = popoverVisible => () => {
    this.setState({ ...TagSelect.defaultState, popoverVisible });
  };

  wrapTriggerSelectTag = id => () => {
    const selected = clone(this.state.selected);
    if (selected.indexOf(id) !== -1) {
      this.setState(
        {
          selected: selected.filter(i => i !== id)
        },
        this.onChangeProps
      );
    } else {
      selected.push(id);
      this.setState(
        {
          selected
        },
        this.onChangeProps
      );
    }
  };

  onChangeProps = () => {
    const { onChange } = this.props;
    if (typeof onChange === 'function') {
      onChange(this.state.selected);
    }
  };

  onSearchInputChange = e => {
    const value = e.target.value;
    this.setState({
      searchInputValue: value.replace(/\s/g, '')
    });
  };

  onPopoverVisibleChange = popoverVisible => {
    if (!popoverVisible) {
      this.setState(TagSelect.defaultState);
    }
    this.setState({ popoverVisible });
  };

  onAddTag = () => {
    const { searchInputValue: name, selectColor: color } = this.state;
    if (name.length > 32) {
      return;
    }
    this.setState({ onAddingTag: true });
    addTag({ name, color })
      .then(() => {
        message.success('添加标签成功');
        this.loadTagsList();
        this.setState({
          searchInputValue: '',
          mode: 'select'
        });
      })
      .catch(() => {
        message.error('添加标签失败');
      })
      .finally(() => {
        this.setState({ onAddingTag: false });
      });
  };

  onUpdateTag = () => {
    const { searchInputValue: name, selectColor: color, currentTag } = this.state;
    if (name.length > 32) {
      return;
    }
    const currentTagId = currentTag._id;
    if (!currentTagId) {
      window.console.log('标签无ID');
      message.error('修改标签失败');
      return;
    }
    this.setState({ onUpdatingTag: true });
    // eslint-disable-next-line
    updateTag({ name, color, tag_id: currentTagId })
      .then(() => {
        message.success('修改标签成功');
        this.loadTagsList();
        this.setState({
          searchInputValue: '',
          mode: 'select'
        });
      })
      .catch(() => {
        message.error('修改标签失败');
      })
      .finally(() => {
        this.setState({ onUpdatingTag: false });
      });
  };

  onDeleteTag = () => {
    const { currentTag, selected } = this.state;
    const currentTagId = currentTag._id;
    if (!currentTagId) {
      window.console.log('标签无ID');
      message.error('修改标签失败');
      return;
    }
    this.setState({ onDeleteingTag: true });
    // eslint-disable-next-line
    deleteTag({ tag_id: currentTagId })
      .then(() => {
        message.success('删除标签成功');
        this.loadTagsList();
        this.setState(
          {
            searchInputValue: '',
            mode: 'select',
            selected: selected.filter(i => i !== currentTagId)
          },
          this.onChangeProps
        );
      })
      .catch(() => {
        message.error('删除标签失败');
      })
      .finally(() => {
        this.setState({ onDeleteingTag: false });
      });
  };

  renderSelectedTags = () => {
    const { selected } = this.state;
    const { tags, tagIdsIndexMap } = this.props;
    return selected.map((tagId, index) => {
      const { name, color } = get(tags, `${tagIdsIndexMap[tagId]}`, {});
      if (!name) {
        return null;
      }
      return (
        <Tag
          key={index}
          value={name}
          color={color}
          closable
          onClose={this.wrapTriggerSelectTag(tagId)}
        />
      );
    });
  };

  renderAddTagBtn = () => {
    const { selected } = this.state;
    const { tagIdsIndexMap } = this.props;
    if (intersection(selected, Object.keys(tagIdsIndexMap)).length) {
      return (
        <Tooltip title="新建标签">
          <Icon type="plus-circle" />
        </Tooltip>
      );
    } else {
      return <span className="to-add-new-tag">新建标签</span>;
    }
  };

  renderPopoverTitle = () => {
    const { mode, searchInputValue } = this.state;
    const titleMap = {
      select: (
        <div className="select-title">
          <Input
            defaultValue={searchInputValue}
            placeholder="搜索标签"
            onChange={this.onSearchInputChange}
          />
          <Icon type="plus-circle" onClick={this.wrapChangeMode('new')} />
        </div>
      ),
      edit: (
        <div className="edit-title">
          <Icon type="left" onClick={this.wrapChangeMode('select')} />
          <span>编辑标签</span>
          <Icon type="close" onClick={this.wrapChangePopover(false)} />
        </div>
      ),
      new: (
        <div className="new-title">
          <Icon type="left" onClick={this.wrapChangeMode('select')} />
          <span>新增标签</span>
          <Icon type="close" onClick={this.wrapChangePopover(false)} />
        </div>
      ),
      delete: (
        <div className="delete-title">
          <Icon type="left" onClick={this.wrapChangeMode('select')} />
          <span>删除标签</span>
          <Icon type="close" onClick={this.wrapChangePopover(false)} />
        </div>
      )
    };

    return titleMap[mode];
  };

  renderPopoverContent = () => {
    const {
      mode,
      selectColor,
      selected,
      searchInputValue,
      onAddingTag,
      onUpdatingTag,
      onDeleteingTag,
      currentTag
    } = this.state;
    const { tags } = this.props;
    const filteredTags = tags.filter(tag => {
      const name = tag.name;
      return name.indexOf(searchInputValue) !== -1;
    });
    const nameError =
      searchInputValue.length > 32 ? <p className="validate-error">标签长度超出限制</p> : null;
    const contentMap = {
      select: (
        <div className="select-content">
          {filteredTags.map((tag, index) => {
            const { color, name, _id } = tag;
            const checked = selected.indexOf(_id) !== -1;
            return (
              <div className="item" key={index} onClick={this.wrapTriggerSelectTag(_id)}>
                <i style={{ backgroundColor: color || tagColors[0] }} className="icon" />
                <span className="value">{name}</span>
                <Icon type="edit" className="edit" onClick={this.wrapChangeMode('edit', tag)} />
                {checked && <Icon type="check" className="check" />}
              </div>
            );
          })}
          {!filteredTags.length && (
            <div className="select-content-new">
              {nameError}
              <ColorBlocks
                key="cb"
                selectColor={selectColor}
                onClick={color => this.setState({ selectColor: color })}
              />
              <div className="operations" key="ct">
                <Button type="primary" onClick={this.onAddTag} loading={onAddingTag}>
                  创建标签
                </Button>
              </div>
            </div>
          )}
        </div>
      ),
      edit: (
        <div className="edit-content">
          <Input
            placeholder="标签名称（不超过32个字符）"
            defaultValue={searchInputValue}
            onChange={this.onSearchInputChange}
          />
          {nameError}
          <ColorBlocks
            key="cb"
            selectColor={selectColor}
            onClick={color => this.setState({ selectColor: color })}
          />
          <div className="operations">
            <Button type="danger" onClick={this.wrapChangeMode('delete', currentTag)}>
              删除
            </Button>
            <Button type="primary" loading={onUpdatingTag} onClick={this.onUpdateTag}>
              完成
            </Button>
          </div>
        </div>
      ),
      new: (
        <div className="new-content">
          <Input
            placeholder="标签名称（不超过32个字符）"
            defaultValue={searchInputValue}
            onChange={this.onSearchInputChange}
          />
          {nameError}
          <ColorBlocks
            key="cb"
            selectColor={selectColor}
            onClick={color => this.setState({ selectColor: color })}
          />
          <div className="operations">
            <Button type="primary" onClick={this.onAddTag} loading={onAddingTag}>
              创建
            </Button>
          </div>
        </div>
      ),
      delete: (
        <div className="delete-content">
          <div className="operations">
            <p className="info">删除标签后，资产中会同时清除该标签，确认删除该标签吗？</p>
            <Button type="danger" onClick={this.onDeleteTag} loading={onDeleteingTag}>
              删除标签
            </Button>
          </div>
        </div>
      )
    };

    return contentMap[mode];
  };

  render() {
    const { popoverVisible } = this.state;
    return (
      <div className="c-tag-select">
        {this.renderSelectedTags()}
        <Popover
          trigger="click"
          title={this.renderPopoverTitle()}
          visible={popoverVisible}
          content={this.renderPopoverContent()}
          overlayClassName="c-tag-select-popover"
          onVisibleChange={this.onPopoverVisibleChange}
        >
          {this.renderAddTagBtn()}
        </Popover>
      </div>
    );
  }
}

TagSelect.propTypes = {
  selected: PropTypes.array,
  onChange: PropTypes.func,
  tags: PropTypes.array,
  tagIdsIndexMap: PropTypes.object,
  loadTags: PropTypes.func
};

const mapStateToProps = state => {
  return {
    tags: get(state, 'tag.tags', []),
    tagIdsIndexMap: get(state, 'tag.tagIdsIndexMap', [])
  };
};

const mapDispatchToProps = dispatch => {
  return {
    ...bindActionCreators(tagActions, dispatch)
  };
};

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(TagSelect);
